<?php
class Forum_Layout
{
    private $_container = array();
    /**
     * Singleton instance
     * 
     * @var Forum_Layout
     */
    private static $_mvcInstance = null;
    
    /**
     * Layout view
     * @var string
     */
    protected $_layout = 'layout_1column';
    
    private $_enabled = true;
    
    private $_request = null;
    
    private $_response = null;
    
    public function __construct($options = null)
    {}
    
    /**
     * 
     * @param string $options
     * @return Forum_Layout
     */
    public static function startMvc($options = null)
    {
        if (null === self::$_mvcInstance) {
            self::$_mvcInstance = new self($options);
        } else {
            self::$_mvcInstance->setViewScriptPath($options);
        }
        return self::$_mvcInstance;
    }
    
    /**
     * Retrieve MVC instance of Forum_Layout object
     * 
     * @return Forum_Layout|null
     */
    public static function getMvcInstance()
    {
        return self::$_mvcInstance;
    }
    
    
    /**
     * Set layout script to use
     *
     * @param  string $name 
     * @return Forum_Layout
     */ 
    public function setLayout($name) 
    {
        $this->_layout = (string) $name;
        return $this;
    }
 
    /**
     * Get current layout script
     * 
     * @return string
     */ 
    public function getLayout() 
    {
        return $this->_layout;
    }
    
    /**
     * Render layout
     *
     * Sets internal script path as last path on script path stack, assigns 
     * layout variables to view, determines layout name using inflector, and 
     * renders layout view script.
     *
     * $name will be passed to the inflector as the key 'script'.
     * 
     * @param  mixed $name 
     * @return mixed
     */ 
    public function render($name = null) 
    { 
        if (null === $name) {
            $name = $this->getLayout() . '.phtml';
        }
        
        $view = new Forum_View();
        return $view->render($name);
    }
    
    /**
     * Assign one or more layout variables
     * 
     * @param  mixed $spec Assoc array or string key; if assoc array, sets each
     * key as a layout variable
     * @param  mixed $value Value if $spec is a key
     * @return Forum_Layout
     * @throws Exception if non-array/string value passed to $spec
     */ 
    public function assign($spec, $value = null) 
    {
        if (is_array($spec)) {
            $this->_container['content'] = $spec['content'];
            return $this;
        }

        if (is_string($spec)) {
            $this->_container[$spec] = $value;
            return $this;
        }

        throw new Exception('Invalid values passed to assign()');
    }
    
    /**
     * Set layout variable
     * 
     * @param  string $key 
     * @param  mixed $value 
     * @return void
     */ 
    public function __set($key, $value) 
    {
        $this->_container[$key] = $value;
    }
 
    /**
     * Get layout variable
     * 
     * @param  string $key
     * @return mixed
     */ 
    public function __get($key) 
    {
        if (isset($this->_container[$key])) {
            return $this->_container[$key];
        }
        return null;
    }
    
    /**
     * Magic call for helpers
     * 
     * @param string $method
     * @param array $attrs
     * @return
     */    
    public function __call($method, $attrs)
    {
        return call_user_func(array('Forum_Helper_' . ucfirst($method), 'getInstance'));
    }
    
    /**
     * Renders layout
     * 
     * @return void
     */ 
    public function dispatchLoopShutdown() 
    { 
        $response = Forum_Controller_Front::getInstance()->getResponse(); 
        
        $this->assign($response->getBody(true)); 
        
        $response->setBody($this->render()); 
    }
 
    /**
     * Disable layout
     *
     * @return Forum_Layout
     */ 
    public function disableLayout() 
    {
        $this->_enabled = false;
        return $this;
    } 

    /**
     * Enable layout 
     * 
     * @return Forum_Layout
     */
    public function enableLayout()
    {
        $this->_enabled = true;
        return $this;
    }

    /**
     * Is layout enabled?
     * 
     * @return bool
     */
    public function isEnabled()
    {
        return $this->_enabled;
    }
}